package com.zjdiepu.www.biz.base;

import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.stereotype.Service;

import com.zjdiepu.www.base.core.AbstractSysUser;
import com.zjdiepu.www.base.core.BaseException;
import com.zjdiepu.www.base.core.BaseService;
import com.zjdiepu.www.base.enums.status.DpStatus;
import com.zjdiepu.www.base.enums.type.CheckResult;
import com.zjdiepu.www.base.enums.type.DataDicType;
import com.zjdiepu.www.base.enums.type.ModeIDType;
import com.zjdiepu.www.base.enums.type.OperateType;
import com.zjdiepu.www.base.enums.type.ResultFlagType;
import com.zjdiepu.www.common.util.CollectionInitUtil;
import com.zjdiepu.www.commpent.RedisObjectClient;
import com.zjdiepu.www.commpent.mapper.base.OtherAttachmentsVoMapper;
import com.zjdiepu.www.dao.base.BaseAccountBusiUnitMapper;
import com.zjdiepu.www.dao.base.OtherAttachmentsMapper;
import com.zjdiepu.www.dao.base.SysPowerMapper;
import com.zjdiepu.www.dao.base.SysUserMapper;
import com.zjdiepu.www.dao.system.BaseSalersmanMapper;
import com.zjdiepu.www.dao.system.SysAppMenuMapper;
import com.zjdiepu.www.ibiz.base.IBaseAccountBusiUnitService;
import com.zjdiepu.www.ibiz.base.ISysUserService;
import com.zjdiepu.www.ibiz.file.IQiniuFileService;
import com.zjdiepu.www.model.base.dto.BaseAccountBusiUnit;
import com.zjdiepu.www.model.base.dto.OtherAttachments;
import com.zjdiepu.www.model.base.dto.SimpleDataDictionary;
import com.zjdiepu.www.model.base.dto.SysPower;
import com.zjdiepu.www.model.base.dto.SysUser;
import com.zjdiepu.www.model.base.ext.BaseAccountBusiUnitExt;
import com.zjdiepu.www.model.base.ext.OtherAttachmentsExt;
import com.zjdiepu.www.model.base.ext.SysUserExt;
import com.zjdiepu.www.model.base.response.Nemu;
import com.zjdiepu.www.model.system.dto.SysAppMenu;
import com.zjdiepu.www.util.ExceptionHelper;

/**
 * 用户表Service层操作实现<br/>
 * @author xiongxiaotun<br/>
 * @time 2017年04月05日 16时02分<br/>
 * @since 1.0<br/>
 */
@Service
public class SysUserServiceImpl extends BaseService implements ISysUserService {
	public static final Logger logger = LoggerFactory.getLogger(SysUserServiceImpl.class);

	@Autowired
	private SysUserMapper sysUserMapper;
	@Autowired
	private SysPowerMapper sysPowerMapper;
	@Autowired
	private SysAppMenuMapper sysAppMenuMapper;
	@Autowired
	private BaseAccountBusiUnitMapper baseAccountBusiUnitMapper;
	@Autowired
	private IBaseAccountBusiUnitService baseAccountBusiUnitService;
	@Autowired
	private BaseSalersmanMapper baseSalersmanMapper;
	@Autowired
	private OtherAttachmentsMapper atherAttachmentsMapper;
	@Autowired
	private OtherAttachmentsVoMapper otherAttachmentsVoMapper;
	@Autowired
	private IQiniuFileService qiniuFileService;
	@Autowired
	private RedisObjectClient redisObjectClient;
	
	@Override
	public List<SysUser> selectMuliByExt(SysUserExt sysUserExt) {
		return sysUserMapper.selectMuliByExt(sysUserExt);
	}
	
	@Override
	public int countMuliByExt(SysUserExt sysUserExt) {
		return sysUserMapper.countMuliByExt(sysUserExt);
	}
	
	@Override
	public List<String> listBankCodes(String bankCodes) {
		List<String> bankCodes_ = CollectionInitUtil.emptyList();
		if(StringUtils.isNotBlank(bankCodes)) {
			String[] bankCodes__ = bankCodes.split("\\|");
			for(String bankCode : bankCodes__) {
				if(StringUtils.isBlank(bankCode)) {
					continue;
				}
				bankCodes_.add(bankCode.trim());
			}
		}
		return bankCodes_;
	}
	
	@Override
	public String getBankNameFromBankCodes(String bankCodes) {
		if(StringUtils.isNotBlank(bankCodes)) {
			String[] bankCodes_ = bankCodes.split("\\|");
			if(ArrayUtils.isNotEmpty(bankCodes_)) {
				return redisObjectClient.execute(new RedisCallback<String>() {
					@Override
					public String doInRedis(RedisConnection redisConnection)
							throws DataAccessException {
						String loanBankNames = "";
						for(String bankCode : bankCodes_) {
							if(StringUtils.isNotBlank(bankCode)) {
								bankCode = bankCode.trim();
								SimpleDataDictionary loanBankDic = redisObjectClient.hGet(redisConnection, SimpleDataDictionary.class.getSimpleName(), bankCode, DataDicType.LOAN_BANK.getCode());
								loanBankNames += (loanBankDic == null ? "" : loanBankDic.getName() + ",");
							}
						}
						return StringUtils.isNotBlank(loanBankNames) ? loanBankNames.substring(0, loanBankNames.length() - 1) : "";
					}
				});
			}
		}
		return "";
	}
	
	@Override
	public SysUser getLoginedUser(String userId) {
		return redisObjectClient.get(userId);
	}
	
	@Override
	public CheckResult checkUser(String currentCompanyId, String currentUserId, boolean admin, String targetCompanyId, String targetUserId) {
		if(StringUtils.isBlank(currentCompanyId)){ //登录用户公司缺失
			return CheckResult.CURRENT_USER_HAS_NO_COMPANY;
		}
		if(StringUtils.isBlank(targetUserId)) { //目标用户为空
			return CheckResult.TARGET_IS_EMPTY;
		}
		if(currentUserId.equals(targetUserId)) { //操作本人
			return CheckResult.TARGET_IS_YOURSELF;
		}
		if(isSuper(targetUserId) && !admin) { //目标用户为超级管理员，而本身不是超级管理员
			return CheckResult.TARGET_IS_SUPER;
		}
		if(StringUtils.isNotBlank(targetCompanyId) && !targetCompanyId.equals(currentCompanyId) && !admin) { //变更公司，而本身不是超级管理员
			return CheckResult.TARGET_CAN_NOT_MOVE_TO_OTHER_COMPANY;
		}
		SysUser dbUser = sysUserMapper.selectByPrimaryKey(targetUserId); //数据库老数据
		if(null == dbUser) {
			return CheckResult.TARGET_IS_MISSING; //操作的数据丢失
		}
		String targetCompanyIdInDb = dbUser.getCompanyId();
		if(!currentCompanyId.equals(targetCompanyIdInDb) && !admin){ //操作非本公司数据，而本身不是超级管理员
			return CheckResult.TARGET_IS_NOT_IN_YOUR_COMPANY;
		}
		return CheckResult.TARGET_IS_NORMAL; //正常
	}
	
	@Override
	public void saveUpdateAndDelete(boolean updateUnit, SysUser sysUser, AbstractSysUser currentUser, OperateType operType) {
		SysUser dbSysUser = null;
		switch (operType) {
		case add:
			sysUser.initInsertData(currentUser.getId(), currentUser.getName());
			sysUserMapper.insert(sysUser);
			if(updateUnit) {
				saveBaseAccountBusiUnit(sysUser, null, currentUser, operType);
			}
			break;
		case edit:
			dbSysUser = sysUserMapper.selectByPrimaryKey(sysUser.getId());
			
			sysUser.initUpdateData(currentUser.getId(), currentUser.getName());
			// 影响的记录数
			int updateCount = sysUserMapper.updateByPrimaryKeySelective(sysUser);
			if(updateCount == 0){
				throw new BaseException(ResultFlagType.MISSING.getCode().toString(),ResultFlagType.MISSING.getValue());
			} else if(updateCount > 1){
				throw new BaseException(ResultFlagType.MULTI_DATA.getCode().toString(),ResultFlagType.MULTI_DATA.getValue());
			}
			if(updateUnit) {
				saveBaseAccountBusiUnit(sysUser, dbSysUser, currentUser, operType);
			}
			break;
		case delete:
			dbSysUser = sysUserMapper.selectByPrimaryKey(sysUser.getId());
			
			sysUser.initDeleteData(currentUser.getId(), currentUser.getName());
			// 影响的记录数
			int deleteCount = sysUserMapper.updateByPrimaryKeySelective(sysUser);
			if(deleteCount == 0){
				throw new BaseException(ResultFlagType.MISSING.getCode().toString(),ResultFlagType.MISSING.getValue());
			} else if(deleteCount > 1){
				throw new BaseException(ResultFlagType.MULTI_DATA.getCode().toString(),ResultFlagType.MULTI_DATA.getValue());
			}
			if(updateUnit) {
				saveBaseAccountBusiUnit(sysUser, dbSysUser, currentUser, operType);
			}
			break;
		default:
			break;
		}
	}
	
	private void saveBaseAccountBusiUnit(SysUser sysUser, SysUser dbSysUser, AbstractSysUser currentUser, OperateType operType){
		//清除内勤关联的业务员ID

		Integer accountType = sysUser.getAccountType();
		if(operType == OperateType.edit) {
			if((accountType != null && accountType == 1) || StringUtils.isBlank(sysUser.getSalersmanId())) { //内勤或者没有关联业务员
				Set<String> emptyFields = new HashSet<String>();
				emptyFields.add("`SALERSMAN_CODE`");
				emptyFields.add("`SALERSMAN_ID`");
				sysUserMapper.clearEmpty(emptyFields, sysUser.getId());
			}
		}
		
		//删除关联的业务员
		if(null != dbSysUser) {
			String salersmanId = dbSysUser.getSalersmanId();
			if(StringUtils.isNotBlank(salersmanId)) {
				BaseAccountBusiUnit baseAccountBusiUnit = new BaseAccountBusiUnit();
				baseAccountBusiUnit.setDpStatus(DpStatus.NORMAL.getCode());
				baseAccountBusiUnit.setUserId(dbSysUser.getId());
				baseAccountBusiUnit.setIdUnit(salersmanId);
				baseAccountBusiUnit = baseAccountBusiUnitMapper.selectRefined(baseAccountBusiUnit);
				if(null != baseAccountBusiUnit) {
					baseAccountBusiUnitMapper.deleteByPrimaryKey(baseAccountBusiUnit.getId());
				}
			}
		}
		
		//添加业务员或管理员的业务员账号
		if(operType == OperateType.edit || operType == OperateType.add) {
			if(accountType != null && (0 == accountType || 2 == accountType)) { //业务员；管理员
				if(StringUtils.isNotBlank(sysUser.getSalersmanId())) {
					BaseAccountBusiUnit baseAccountBusiUnit = new BaseAccountBusiUnit();
					baseAccountBusiUnit.setUserId(sysUser.getId());
					baseAccountBusiUnit.setIdUnit(sysUser.getSalersmanId());
					baseAccountBusiUnit.setCodeUnit(sysUser.getSalersmanCode());
					baseAccountBusiUnitService.saveOrUpdate(baseAccountBusiUnit, currentUser);
				}
			}
		}
		
	}
	
	@Override
	public List<SysUser> selectByExt(SysUserExt sysUserExt) {
		return sysUserMapper.selectByExt(sysUserExt);
	}
	
	@Override
	public int countByExt(SysUserExt sysUserExt){
		return sysUserMapper.countByExt(sysUserExt);
	}
	
	@Override
	public SysUser selectById(String id) {
		return sysUserMapper.selectByPrimaryKey(id);
	}
	
	@Override
	public void clearEmpty(Set<String> fieldNames, String id) {
		if(CollectionUtils.isNotEmpty(fieldNames)){
			sysUserMapper.clearEmpty(fieldNames, id);
		}
	}

	@Override
	public SysUser selectByName(String name, boolean mobile) {
		SysUser sysUser = sysUserMapper.selectByName(name);
		if(sysUser != null) {
			if(DpStatus.INVALID.getCode() == sysUser.getDpStatus()) {
				ExceptionHelper.thow("999", "该账号已被禁用");
			} else if(DpStatus.DELETED.getCode() == sysUser.getDpStatus()) {
				ExceptionHelper.thow("999", "该账号已被删除");
			}
			String userId = sysUser.getId();
			OtherAttachmentsExt otherAttachmentsExt = new OtherAttachmentsExt();
			otherAttachmentsExt.setBaseWhere();
			otherAttachmentsExt.setRows(1);
			otherAttachmentsExt.setDataid(userId);
			otherAttachmentsExt.setModeId(ModeIDType.YONGHUGUANLI.getCode());
			List<OtherAttachments> otherAttachments = atherAttachmentsMapper.selectByExt(otherAttachmentsExt);
			
			if(CollectionUtils.isNotEmpty(otherAttachments)) {
				OtherAttachments otherAttachment = otherAttachments.get(0);
				String ossPath = otherAttachment.getOssPath();
				sysUser.setHeaderImageSrc(qiniuFileService.getURL(ossPath));
			}
			if(mobile) {
				//查询用户APP菜单
				Map<String, List<Nemu>> userNemus = new LinkedHashMap<String, List<Nemu>>();
				List<SysAppMenu> topAppMenus = sysAppMenuMapper.selectByUserIdAndParentId(userId, false, null);
				if(CollectionUtils.isNotEmpty(topAppMenus)) {
					SysAppMenu topAppMenu = topAppMenus.get(0); //顶级辅助菜单
					String topId = topAppMenu.getId();
					List<SysAppMenu> secondAppMenus = sysAppMenuMapper.selectByUserIdAndParentId(userId, false, topId); //二级大菜单
					List<Nemu> secondNemus = CollectionInitUtil.emptyList();
					for(SysAppMenu secondAppMenu : secondAppMenus){
						Nemu nemu = new Nemu();
						BeanUtils.copyProperties(secondAppMenu, nemu);
						secondNemus.add(nemu);
					}
					userNemus.put("top", secondNemus);
					if(CollectionUtils.isNotEmpty(secondNemus)) {
						List<SysAppMenu> allAppMenus = sysAppMenuMapper.selectByUserIdAndParentId(userId, true, null); //预备数据，一次全部查询
						allAppMenus.remove(topAppMenu);
						allAppMenus.removeAll(secondAppMenus);
						List<Nemu> allNemus = parseAllAppNemus(allAppMenus);
						List<Nemu> remainNemus = CollectionInitUtil.emptyList();
						for(Nemu secondNemu : secondNemus){
							String powerCode = secondNemu.getPowerCode();
							String secondId = secondNemu.getId();
							List<Nemu> childrenNemus = filterNemusFromAllNemus(allNemus, secondId, remainNemus);
							remainNemus = setChildrenNemus(childrenNemus, remainNemus);
							userNemus.put(powerCode, childrenNemus);
						}
					}
				}
				sysUser.setAppNemus(userNemus);
			} else {
				//查询用户权限
				Map<String, List<Nemu>> userNemus = new LinkedHashMap<String, List<Nemu>>();
				List<SysPower> topPowers = sysPowerMapper.selectByUserIdAndParentId(userId, 1, false, null);
				if(CollectionUtils.isNotEmpty(topPowers)) {
					SysPower topPower = topPowers.get(0); //顶级辅助菜单
					String topId = topPower.getId();
					List<SysPower> secondPowers = sysPowerMapper.selectByUserIdAndParentId(userId, 1, false, topId); //二级大菜单
					List<Nemu> secondNemus = CollectionInitUtil.emptyList();
					for(SysPower secondPower : secondPowers){
						Nemu nemu = new Nemu();
						BeanUtils.copyProperties(secondPower, nemu);
						secondNemus.add(nemu);
					}
					userNemus.put("top", secondNemus);
					if(CollectionUtils.isNotEmpty(secondNemus)) {
						List<SysPower> allPowers = sysPowerMapper.selectByUserIdAndParentId(userId, 1, true, null); //预备数据，一次全部查询
						allPowers.remove(topPower);
						allPowers.removeAll(secondPowers);
						List<Nemu> allNemus = parseAllNemus(allPowers);
						List<Nemu> remainNemus = CollectionInitUtil.emptyList();
						for(Nemu secondNemu : secondNemus){
							String powerCode = secondNemu.getPowerCode();
							String secondId = secondNemu.getId();
							List<Nemu> childrenNemus = filterNemusFromAllNemus(allNemus, secondId, remainNemus);
							remainNemus = setChildrenNemus(childrenNemus, remainNemus);
							userNemus.put(powerCode, childrenNemus);
						}
					}
				}
				sysUser.setNemus(userNemus);
			}
			
			
			BaseAccountBusiUnitExt baseAccountBusiUnitExt = new BaseAccountBusiUnitExt();
			baseAccountBusiUnitExt.setBaseWhere();
			baseAccountBusiUnitExt.withOutPage();
			baseAccountBusiUnitExt.setUserId(userId);
			List<BaseAccountBusiUnit> baseAccountBusiUnits = baseAccountBusiUnitMapper.selectByExt(baseAccountBusiUnitExt);
			if(CollectionUtils.isEmpty(baseAccountBusiUnits)) {
				return sysUser;
			}
			//管理员也可能关联一个业务员账号，已经维护到sys_user表，不需要再查询赋值  2017.10.31
//			if(sysUser.getAccountType() != null && 0 == sysUser.getAccountType() && baseAccountBusiUnits.size() == 1) { //业务员
//				BaseAccountBusiUnit baseAccountBusiUnit = baseAccountBusiUnits.get(0);
//				String salesmanId = baseAccountBusiUnit.getIdUnit(); //业务员ID
//				BaseSalersman baseSalersman = baseSalersmanMapper.selectByPrimaryKey(salesmanId);
//				if(baseSalersman != null) {
//					sysUser.setSalersmanCode(baseSalersman.getSalersmanCode());
//					sysUser.setSalersmanId(baseSalersman.getId());
//				}
//			}
			
			
			//负责的组织机构
			List<String> codeUnits = baseAccountBusiUnits.stream().map(item -> item.getCodeUnit()).collect(Collectors.toList());
			sysUser.setCodeUnits(codeUnits);
		}
		return sysUser;
	}

	@Override
	public int countRefined(SysUser sysUser) {
		return sysUserMapper.countRefined(sysUser);
	}

	@Override
	public SysUser selectRefined(SysUser sysUser) {
		return sysUserMapper.selectRefined(sysUser);
	}

	@Override
	public boolean repeat(SysUser sysUser) {
		int count = countRefined(sysUser);
		if(count > 1) {
			return true;
		}
		if(count == 0) {
			return false;
		}
		
		if(StringUtils.isBlank(sysUser.getId())) {
			return true;
		}
		SysUser dbItem = selectRefined(sysUser);
		if(null == dbItem) {
			return false;
		}
		return !sysUser.getId().equals(dbItem.getId());
	}

	/* 
	* @author zhangpp
	* <p>Title: selectByExtServiceDep</p> 
	* <p>Description: </p> 
	* @param sysUserExt
	* @return 
	* @see com.api.user.service.ISysUserService#selectByExtServiceDep(com.api.user.entity.ext.SysUserExt) 
	* @version V1.0
	*/
	@Override
	public List<SysUser> selectByExtServiceDep(SysUserExt sysUserExt) {
		
		return sysUserMapper.selectByExtDep(sysUserExt);
	}
	
	/**
	 * 子菜单赋值
	 * @param nemus
	 * @param remainNemus
	 */
	private List<Nemu> setChildrenNemus(List<Nemu> nemus, List<Nemu> remainNemus) {
		List<Nemu> remainNemus_ = CollectionInitUtil.emptyList();
		if(CollectionUtils.isEmpty(remainNemus) || CollectionUtils.isEmpty(remainNemus)) {
			return remainNemus_;
		}
		for(Nemu nemu : nemus) {
			String id = nemu.getId();
			List<Nemu> children = CollectionInitUtil.emptyList();
			for(Nemu remainNemu : remainNemus) {
				if(id.equals(remainNemu.getParentId())) {
					children.add(remainNemu);
				} else {
					remainNemus_.add(remainNemu);
				}
			}
			nemu.setChildren(children);
			remainNemus_ = setChildrenNemus(children, remainNemus_);
		}
		return remainNemus_;
	}
	
	/**
	 * 过滤出菜单
	 * @param allNemus
	 * @param parentId
	 */
	private List<Nemu> filterNemusFromAllNemus(List<Nemu> allNemus, String parentId, List<Nemu> remainNemus){
		List<Nemu> nemus = CollectionInitUtil.emptyList();
		if(CollectionUtils.isEmpty(allNemus) || StringUtils.isBlank(parentId)) {
			return nemus;
		}
		for(Nemu nemu : allNemus) {
			if(parentId.equals(nemu.getParentId())) {
				nemus.add(nemu);
			} else {
				remainNemus.add(nemu);
			}
		}
		return nemus;
	}
	
	/**
	 * 获取所有菜单
	 * @param allPowers
	 * @return
	 */
	private List<Nemu> parseAllNemus(List<SysPower> allPowers){
		List<Nemu> nemus = CollectionInitUtil.emptyList();
		if(CollectionUtils.isEmpty(allPowers)) {
			return nemus;
		}
		for(SysPower sysPower : allPowers) {
			Nemu nemu = new Nemu();
			BeanUtils.copyProperties(sysPower, nemu);
			nemus.add(nemu);
		}
		return nemus;
	}
	
	/**
	 * 获取所有菜单
	 * @param allPowers
	 * @return
	 */
	private List<Nemu> parseAllAppNemus(List<SysAppMenu> allAppMenus){
		List<Nemu> nemus = CollectionInitUtil.emptyList();
		if(CollectionUtils.isEmpty(allAppMenus)) {
			return nemus;
		}
		for(SysAppMenu sysAppMenu : allAppMenus) {
			Nemu nemu = new Nemu();
			nemu.setId(sysAppMenu.getId());
			nemu.setParentId(sysAppMenu.getParentId());
			nemu.setPowerCode(sysAppMenu.getMenuCode());
			nemu.setName(sysAppMenu.getMenuName());
			nemus.add(nemu);
		}
		return nemus;
	}
}
